<html>
 <head>
  <meta charset="UTF-8">
 </head>
 <body>
  <h1 data-lake-id="oaZkH" id="oaZkH"><span data-lake-id="u6a3b8280" id="u6a3b8280">典型回答</span></h1>
  <p data-lake-id="u19d09316" id="u19d09316"><span data-lake-id="u5f7b5d1c" id="u5f7b5d1c" style="color: #000000">​</span><br></p>
  <h2 data-lake-id="DpHEz" id="DpHEz"><span data-lake-id="u28026760" id="u28026760" style="color: #000000">TCP队头阻塞</span></h2>
  <p data-lake-id="u4cd9b843" id="u4cd9b843"><span data-lake-id="u605a6e60" id="u605a6e60" style="color: #000000">​</span><br></p>
  <p data-lake-id="uf7ad85b6" id="uf7ad85b6"><span data-lake-id="u52dba56c" id="u52dba56c" class="lake-fontsize-12">HTTP/2虽然</span><strong><span data-lake-id="ucb71ca68" id="ucb71ca68" class="lake-fontsize-12">解决了HTTP队头阻塞的问题</span></strong><strong><span data-lake-id="u6bb7378e" id="u6bb7378e" class="lake-fontsize-12" style="color: #000000">。</span></strong><span data-lake-id="u88559f19" id="u88559f19" class="lake-fontsize-12" style="color: #000000">HTTP/2仍然会存在TCP队头阻塞的问题，那是因为HTTP/2其实还是依赖TCP协议实现的。</span></p>
  <p data-lake-id="uf81d25d1" id="uf81d25d1"><span data-lake-id="u66c488a3" id="u66c488a3" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="ud27dd552" id="ud27dd552" style="text-align: justify"><span data-lake-id="u9f6857b3" id="u9f6857b3" class="lake-fontsize-12" style="color: #000000">TCP传输过程中会把数据拆分为一个个</span><strong><span data-lake-id="u99024eff" id="u99024eff" class="lake-fontsize-12" style="color: #000000">按照顺序</span></strong><span data-lake-id="u3138540f" id="u3138540f" class="lake-fontsize-12" style="color: #000000">排列的数据包，这些数据包通过网络传输到了接收端，接收端再</span><strong><span data-lake-id="ua4bec1c7" id="ua4bec1c7" class="lake-fontsize-12" style="color: #000000">按照顺序</span></strong><span data-lake-id="ua7c62f38" id="ua7c62f38" class="lake-fontsize-12" style="color: #000000">将这些数据包组合成原始数据，这样就完成了数据传输。</span></p>
  <p data-lake-id="uc3b9b2f5" id="uc3b9b2f5" style="text-align: justify"><span data-lake-id="u20847f02" id="u20847f02" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="u457e7e3b" id="u457e7e3b" style="text-align: justify"><span data-lake-id="u58de7b62" id="u58de7b62" class="lake-fontsize-12" style="color: #000000">但是如果其中的某一个数据包没有按照顺序到达，接收端会一直保持连接等待数据包返回，这时候就会阻塞后续请求。这就发生了</span><strong><span data-lake-id="ubf485daa" id="ubf485daa" class="lake-fontsize-12" style="color: #000000">TCP队头阻塞</span></strong><span data-lake-id="ub384b271" id="ub384b271" class="lake-fontsize-12" style="color: #000000">。</span></p>
  <p data-lake-id="udaa4c2bf" id="udaa4c2bf" style="text-align: justify"><span data-lake-id="u18ab8622" id="u18ab8622" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="ucd0b6569" id="ucd0b6569" style="text-align: justify"><span data-lake-id="u775b5be0" id="u775b5be0" class="lake-fontsize-12" style="color: #000000">HTTP/1.1的管道化持久连接也是使得同一个TCP链接可以被多个HTTP使用，但是HTTP/1.1中规定一个域名可以有6个TCP连接。而HTTP/2中，同一个域名只是用一个TCP连接。</span></p>
  <p data-lake-id="u585914e2" id="u585914e2" style="text-align: justify"><span data-lake-id="ud4fa0e49" id="ud4fa0e49" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="u167a51b8" id="u167a51b8" style="text-align: justify"><span data-lake-id="u2255aece" id="u2255aece" class="lake-fontsize-12" style="color: #000000">所以，</span><strong><span data-lake-id="u9fdaf86b" id="u9fdaf86b" class="lake-fontsize-12" style="color: #000000">在HTTP/2中，TCP队头阻塞造成的影响会更大</span></strong><span data-lake-id="u68bf7ac1" id="u68bf7ac1" class="lake-fontsize-12" style="color: #000000">，因为HTTP/2的多路复用技术使得多个请求其实是基于同一个TCP连接的，那如果某一个请求造成了TCP队头阻塞，那么多个请求都会受到影响。</span></p>
  <p data-lake-id="u45f2a7de" id="u45f2a7de" style="text-align: justify"><span data-lake-id="ud24cd790" id="ud24cd790" style="color: #000000">​</span><br></p>
  <h2 data-lake-id="DIAVV" id="DIAVV"><span data-lake-id="u8305c0d9" id="u8305c0d9" style="color: #000000">TCP握手时长</span></h2>
  <p data-lake-id="u6926624f" id="u6926624f"><span data-lake-id="u5ddb98ba" id="u5ddb98ba" style="color: #000000">​</span><br></p>
  <p data-lake-id="u0b12f8dd" id="u0b12f8dd" style="text-align: justify"><span data-lake-id="ud0ec1af0" id="ud0ec1af0" class="lake-fontsize-12" style="color: #000000">一提到TCP协议，大家最先想到的一定是他的三次握手与四次关闭的特性。</span></p>
  <p data-lake-id="u639f0ea8" id="u639f0ea8" style="text-align: justify"><span data-lake-id="u246cda8f" id="u246cda8f" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="ubafc4eea" id="ubafc4eea" style="text-align: justify"><strong><span data-lake-id="ua851f533" id="ua851f533" class="lake-fontsize-12" style="color: #000000">因为TCP是一种可靠通信协议，而这种可靠就是靠三次握手实现的，通过三次握手，TCP在传输过程中可以保证接收方收到的数据是完整，有序，无差错的。</span></strong></p>
  <p data-lake-id="u5c27111f" id="u5c27111f" style="text-align: justify"><strong><span data-lake-id="ua660191c" id="ua660191c" class="lake-fontsize-12" style="color: #000000">​</span></strong><br></p>
  <p data-lake-id="u68c8d50b" id="u68c8d50b" style="text-align: justify"><span data-lake-id="u5e72ae96" id="u5e72ae96" class="lake-fontsize-12" style="color: #000000">但是，问题是三次握手是需要消耗时间的，这里插播一个关于网络延迟的概念。</span></p>
  <p data-lake-id="uf5ab6af1" id="uf5ab6af1" style="text-align: justify"><span data-lake-id="u7d83d078" id="u7d83d078" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="u07ce29c1" id="u07ce29c1" style="text-align: justify"><span data-lake-id="u06ad214e" id="u06ad214e" class="lake-fontsize-12" style="color: #000000">网络延迟又称为 RTT（Round Trip Time）。他是指一个请求从客户端浏览器发送一个请求数据包到服务器，再从服务器得到响应数据包的这段时间。RTT 是反映网络性能的一个重要指标。</span></p>
  <p data-lake-id="ud04bd15c" id="ud04bd15c" style="text-align: justify"><img src="https://cdn.nlark.com/yuque/0/2022/jpeg/5378072/1668598284247-2d3cb263-0414-428a-81f2-eeebbb40b444.jpeg?x-oss-process=image%2Fwatermark%2Ctype_d3F5LW1pY3JvaGVp%2Csize_23%2Ctext_SmF2YSA4IEd1IFA%3D%2Ccolor_FFFFFF%2Cshadow_50%2Ct_80%2Cg_se%2Cx_10%2Cy_10"></p>
  <p data-lake-id="u8b5a40f2" id="u8b5a40f2" style="text-align: justify"><span data-lake-id="ucfba2e19" id="ucfba2e19" class="lake-fontsize-12" style="color: #000000">我们知道，TCP三次握手的过程客户端和服务器之间需要交互三次，那么也就是说需要消耗1.5 RTT。</span></p>
  <p data-lake-id="u20004741" id="u20004741" style="text-align: justify"><span data-lake-id="ub8222ec2" id="ub8222ec2" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="u5d65641d" id="u5d65641d" style="text-align: justify"><span data-lake-id="u20181aaf" id="u20181aaf" class="lake-fontsize-12" style="color: #000000">另外，如果使用的是安全的HTTPS协议，就还需要使用TLS协议进行安全数据传输，这个过程又要消耗一个RTT（TLS不同版本的握手机制不同，这里按照最小的消耗来算）</span></p>
  <p data-lake-id="u21d1fc9c" id="u21d1fc9c" style="text-align: justify"><span data-lake-id="u7e96bd17" id="u7e96bd17" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="u609d49a2" id="u609d49a2" style="text-align: justify"><span data-lake-id="ubd0c8d50" id="ubd0c8d50" class="lake-fontsize-12" style="color: #000000">那么也就是说，一个纯HTTP/2的连接，需要消耗1.5个RTT，如果是一个HTTPS连接，就需要消耗3-4个RTT。</span></p>
  <p data-lake-id="ucb8f7673" id="ucb8f7673" style="text-align: justify"><span data-lake-id="ud07868b9" id="ud07868b9" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="u77709485" id="u77709485" style="text-align: justify"><span data-lake-id="ue2d62796" id="ue2d62796" class="lake-fontsize-12" style="color: #000000">而具体消耗的时长根据服务器和客户端之间的距离则不尽相同，如果比较近的话，消耗在100ms以内，对于用户来说可能没什么感知，但是如果一个RTT的耗时达到300-400ms，那么，一次连接建立过程总耗时可能要达到一秒钟左右，这时候，用户就会明显的感知到网页加载很慢。</span></p>
  <p data-lake-id="ua044a776" id="ua044a776" style="text-align: justify"><span data-lake-id="u2de82b04" id="u2de82b04" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <h2 data-lake-id="aZLtL" id="aZLtL"><span data-lake-id="u15a6cf57" id="u15a6cf57" style="color: #000000">升级TCP是否可行？</span></h2>
  <p data-lake-id="u8ca62bdf" id="u8ca62bdf" style="text-align: justify"><span data-lake-id="u1e435ca1" id="u1e435ca1" class="lake-fontsize-12" style="color: #000000">基于上面我们提到的这些问题，很多人提出来说：既然TCP存在这些问题，并且我们也知道这些问题的存在，甚至解决方案也不难想到，为什么不能对协议本身做一次升级，解决这些问题呢？</span></p>
  <p data-lake-id="u7371206b" id="u7371206b" style="text-align: justify"><span data-lake-id="ufcbe13e2" id="ufcbe13e2" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="ufb960e50" id="ufb960e50" style="text-align: justify"><span data-lake-id="u4655b8e2" id="u4655b8e2" class="lake-fontsize-12" style="color: #000000">其实，这就涉及到一个”</span><strong><span data-lake-id="ud7403925" id="ud7403925" class="lake-fontsize-12" style="color: #000000">协议僵化</span></strong><span data-lake-id="u3ec34d3c" id="u3ec34d3c" class="lake-fontsize-12" style="color: #000000">“的问题。</span></p>
  <p data-lake-id="ub04754a5" id="ub04754a5" style="text-align: justify"><span data-lake-id="uc343c9e9" id="uc343c9e9" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="u439981e9" id="u439981e9" style="text-align: justify"><span data-lake-id="ua6361d06" id="ua6361d06" class="lake-fontsize-12" style="color: #000000">这样讲，我们在互联网上浏览数据的时候，数据的传输过程其实是极其复杂的。</span></p>
  <p data-lake-id="u52cb5702" id="u52cb5702" style="text-align: justify"><span data-lake-id="ue4c940b7" id="ue4c940b7" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="u7c979b4a" id="u7c979b4a" style="text-align: justify"><span data-lake-id="u2ecbedef" id="u2ecbedef" class="lake-fontsize-12" style="color: #000000">我们知道的，想要在家里使用网络有几个前提，首先我们要通过运行商开通网络，并且需要使用路由器，而路由器就是网络传输过程中的一个中间设备。</span></p>
  <p data-lake-id="u125c32f3" id="u125c32f3" style="text-align: justify"><span data-lake-id="u523c78e7" id="u523c78e7" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="u001abee9" id="u001abee9" style="text-align: justify"><span data-lake-id="ua3e5b394" id="ua3e5b394" class="lake-fontsize-12" style="color: #000000">中间设备是指插入在数据终端和信号转换设备之间，完成调制前或解调后某些附加功能的辅助设备。例如集线器、交换机和无线接入点、路由器、安全解调器、通信服务器等都是中间设备。</span></p>
  <p data-lake-id="udf9a9e65" id="udf9a9e65" style="text-align: justify"><span data-lake-id="uac76edb0" id="uac76edb0" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="uab4d09ce" id="uab4d09ce" style="text-align: justify"><span data-lake-id="u3e5dadd5" id="u3e5dadd5" class="lake-fontsize-12" style="color: #000000">在我们看不到的地方，这种中间设备还有很多很多，</span><strong><span data-lake-id="u9103962a" id="u9103962a" class="lake-fontsize-12" style="color: #000000">一个网络需要经过无数个中间设备的转发才能到达终端用户。</span></strong></p>
  <p data-lake-id="u90cec452" id="u90cec452" style="text-align: justify"><strong><span data-lake-id="ub7304d9a" id="ub7304d9a" class="lake-fontsize-12" style="color: #000000">​</span></strong><br></p>
  <p data-lake-id="ubffa9bb1" id="ubffa9bb1" style="text-align: justify"><span data-lake-id="ud2deeefe" id="ud2deeefe" class="lake-fontsize-12" style="color: #000000">如果TCP协议需要升级，那么意味着需要这些中间设备都能支持新的特性，我们知道路由器我们可以重新换一个，但是其他的那些中间设备呢？尤其是那些比较大型的设备呢？更换起来的成本是巨大的。</span></p>
  <p data-lake-id="u413fce0f" id="u413fce0f" style="text-align: justify"><span data-lake-id="ue0264ec1" id="ue0264ec1" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="uc085e89a" id="uc085e89a" style="text-align: justify"><span data-lake-id="u22db71f2" id="u22db71f2" class="lake-fontsize-12" style="color: #000000">而且，除了中间设备之外，操作系统也是一个重要的因素，</span><strong><span data-lake-id="uc99a8d20" id="uc99a8d20" class="lake-fontsize-12" style="color: #000000">因为TCP协议需要通过操作系统内核来实现，而操作系统的更新也是非常滞后的。</span></strong></p>
  <p data-lake-id="uf1591fe8" id="uf1591fe8" style="text-align: justify"><strong><span data-lake-id="u14cebcd7" id="u14cebcd7" class="lake-fontsize-12" style="color: #000000">​</span></strong><br></p>
  <p data-lake-id="u4a6a5c39" id="u4a6a5c39" style="text-align: justify"><span data-lake-id="uea250580" id="uea250580" class="lake-fontsize-12" style="color: #000000">所以，这种问题就被称之为”中间设备僵化”，也是导致”协议僵化”的重要原因。这也是限制着TCP协议更新的一个重要原因。</span></p>
  <p data-lake-id="u8b62c1a0" id="u8b62c1a0" style="text-align: justify"><span data-lake-id="u312fc031" id="u312fc031" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="uc80cb115" id="uc80cb115" style="text-align: justify"><span data-lake-id="u85aed48d" id="u85aed48d" class="lake-fontsize-12" style="color: #000000">所以，近些年来，由IETF标准化的许多TCP新特性都因缺乏广泛支持而没有得到广泛的部署或使用！</span></p>
  <h2 data-lake-id="zCbgZ" id="zCbgZ"><span data-lake-id="u828dc237" id="u828dc237" style="color: #000000">放弃TCP？</span></h2>
  <p data-lake-id="u1496ff3e" id="u1496ff3e" style="text-align: justify"><span data-lake-id="ue60ef501" id="ue60ef501" class="lake-fontsize-12" style="color: #000000">上面提到的这些问题的根本原因都是因为HTTP/2是基于TCP实现导致的，而TCP协议自身的升级又是很难实现的。</span></p>
  <p data-lake-id="u9459069d" id="u9459069d" style="text-align: justify"><span data-lake-id="u15494a49" id="u15494a49" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="u6872b1be" id="u6872b1be" style="text-align: justify"><span data-lake-id="u0670458c" id="u0670458c" class="lake-fontsize-12" style="color: #000000">那么，剩下的解决办法就只有一条路，那就是放弃TCP协议。</span></p>
  <p data-lake-id="ue70e7cc1" id="ue70e7cc1" style="text-align: justify"><span data-lake-id="u9bb7e7a7" id="u9bb7e7a7" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="ucf934f00" id="ucf934f00" style="text-align: justify"><span data-lake-id="u6a4caf12" id="u6a4caf12" class="lake-fontsize-12" style="color: #000000">放弃TCP的话，就又有两个新的选择，是使用其他已有的协议，还是重新创造一个协议呢？</span></p>
  <p data-lake-id="u2aef25f0" id="u2aef25f0" style="text-align: justify"><span data-lake-id="u36607d3f" id="u36607d3f" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="u8b0378c9" id="u8b0378c9" style="text-align: justify"><span data-lake-id="udd25b9ab" id="udd25b9ab" class="lake-fontsize-12" style="color: #000000">看到这里，聪明的读者一定也想到了，</span><strong><span data-lake-id="u13e2352a" id="u13e2352a" class="lake-fontsize-12" style="color: #000000">创造新的协议一样会受到中间设备僵化的影响</span></strong><span data-lake-id="u1fcd86d8" id="u1fcd86d8" class="lake-fontsize-12" style="color: #000000">。近些年来，因为在互联网上部署遭遇很大的困难，创造新型传输层协议的努力基本上都失败了！</span></p>
  <p data-lake-id="u31e1e1c0" id="u31e1e1c0" style="text-align: justify"><span data-lake-id="u25de7d6a" id="u25de7d6a" class="lake-fontsize-12" style="color: #000000">​</span><br></p>
  <p data-lake-id="uf9210af8" id="uf9210af8" style="text-align: justify"><span data-lake-id="u83476e0e" id="u83476e0e" class="lake-fontsize-12" style="color: #000000">所以，想要升级新的HTTP协议，那么就只剩一条路可以走了，那就是基于已有的协议做一些改造和支持，UDP就是一个绝佳的选择了。</span></p>
 </body>
</html>